#include "CircleQueue.hpp"
#define DEFAULT_SIZE 15

template <class T>
CircleQueue<T>::CircleQueue()
{
  d_front = d_rear = -1;
  d_maxsize = DEFAULT_SIZE;
  d_size = 0;
  d_arr = new T[d_maxsize];
}

//构造函数
template <class T>
CircleQueue<T>::CircleQueue(size_t size)
{
  d_size = 0;
  d_maxsize = size;
  d_front = d_rear = -1;
  d_arr = new T[d_maxsize];
}

//析构函数
template <class T>
CircleQueue<T>::~CircleQueue()
{
  delete[] d_arr;
}

//检查环形队列是否为满载
template <class T>
bool CircleQueue<T>::is_full() const
{
  return (d_rear == d_maxsize - 1 && d_front == 0) || (d_rear == d_front - 1);
}

//判断环形队列是否为空
template <class T>
bool CircleQueue<T>::is_empty() const
{
  return d_front == -1 || d_rear == -1;
}

//入队操作
template <class T>
void CircleQueue<T>::enque(const T &value)
{
  if (is_full())
  {
    std::cout << "环形队列已满" << std::endl;
    return;
  }
  else if (d_front == -1)
  {
    d_rear = d_front = 0;
  }
  else if (d_rear == d_maxsize - 1 && d_front != 0)
  {
    d_rear = 0;
  }
  else
  {
    d_rear++;
  }
  d_arr[d_rear] = value;
  d_size++;
}

//踢队操作
template <class T>
T CircleQueue<T>::deque()
{
  if (is_empty())
  {
    std::cout << "环形队列为空!!" << std::endl;
    return T();
  }

  T data = d_arr[d_front];

  if (d_front == d_rear)
  {
    d_front = -1;
    d_rear = -1;
  }
  else if (d_front == d_size - 1)
  {
    d_front = 0;
  }
  else
  {
    d_front++;
  }
  d_size--;
  return data;
}

//获取队头部元素
template <class T>
T CircleQueue<T>::front() const
{
  return d_arr[d_front];
}

//获取队尾元素
template <class T>
T CircleQueue<T>::rear() const
{
  return d_arr[d_rear];
}

//获取队列尺寸
template <class T>
const size_t CircleQueue<T>::size()
{
  return d_size;
}

//获取队列内部的缓存指针
template <class T>
const T *CircleQueue<T>::buffer()
{
  return d_arr;
}

//遍历
template <class R>
std::ostream &operator<<(std::ostream &os, CircleQueue<R> &q)
{

  const R *buf = q.d_arr;

  if (q.d_front == -1)
  {
    os << "CircleQueue为空" << std::endl;
  }
  else if (q.d_rear >= q.d_front)
  {
    for (auto i = q.d_front; i <= q.d_rear; i++)
    {
      os << buf[i] << ",";
    }
  }
  else
  {
    for (auto i = q.d_front; i < q.d_size; i++)
    {
      os << buf[i] << ",";
    }

    for (auto i = 0; i <= q.d_rear; i++)
    {
      os << buf[i] << ",";
    }
  }
  os << std::endl;
  return os;
}